/*  
 *  test.c - Linux kernel module(lkm) test.
 */
#include <linux/module.h>	/* Needed by all modules */
#include <linux/kernel.h>	/* Needed for KERN_DEBUG */
#include <linux/init.h>		/* Needed for the macros */
#include <linux/jiffies.h>	/* Needed for the jiffies */
#include <linux/delay.h>	/* Needed for the delay */
#include <linux/crypto.h>
#include <linux/err.h>
#include <linux/scatterlist.h>

#define DRIVER_AUTHOR "Sachin Desai <sachinpdesai@hotmail.com>"
#define DRIVER_DESC   "Crypto test"

static unsigned int delay_cnt = 10;
module_param (delay_cnt, uint, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
MODULE_PARM_DESC(delay_cnt, "A unsigned integer");

static int __init init_crypto_test(void)
{
    int i;

    cycles_t start_cycle, end_cycle;
    unsigned long total_cycles = 0;

    unsigned long start_jiffies, end_jiffies;
    unsigned long total_jiffies = 0;

    struct scatterlist sg[2];
    char result[128];
    struct crypto_hash *tfm;
    struct hash_desc desc;

    tfm = crypto_alloc_hash("md5", 0, CRYPTO_ALG_ASYNC);
    if (IS_ERR(tfm))
        return(-1);
        
    start_cycle = get_cycles();
    start_jiffies = jiffies;

    /* ... set up the scatterlists ... */
    for (i = 0; i < delay_cnt; i++) {
        mdelay(i);
    }

    end_cycle = get_cycles();
    end_jiffies = jiffies;

    total_cycles += end_cycle - start_cycle;
    total_jiffies += end_jiffies - start_jiffies;

    printk(KERN_DEBUG "Test cylces = %ld\n", total_cycles);
    printk(KERN_DEBUG "Test jiffies = %ld\n", total_jiffies);

    desc.tfm = tfm;
    desc.flags = 0;

    if (crypto_hash_digest(&desc, sg, 2, result))
        return(-1);

    crypto_free_hash(tfm);

    return(0);
}

static void __exit exit_crypto_test(void)
{
}

module_init(init_crypto_test);
module_exit(exit_crypto_test);

/* 
 * Get rid of taint message by declaring code as GPL. 
 */
MODULE_LICENSE("GPL");
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
